﻿#include "FITKAbaAssembly.h"
#include "FITKAbaRefPoint.h"
#include "FITKAbaTransform.h"
#include "FITKAbaEngineeringFeature.h"
#include "FITKAbaWire.h"
#include "FITK_Interface/FITKInterfaceModel/FITKNodeList.h"
#include "FITK_Interface/FITKInterfaceModel/FITKComponentManager.h"
#include "FITK_Interface/FITKInterfaceModel/FITKModelSet.h"
#include "FITK_Interface/FITKInterfaceModel/FITKModelSet.h"
#include "FITK_Interface/FITKInterfaceModel/FITKModelSet.h" 
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaConnectorAssignmentManager.h"
#include "FITK_Kernel/FITKCore/FITKDataRepo.h"
#include "FITK_Kernel/FITKCore/FITKVec3D.h"


namespace Interface
{

    FITKAbaAssembly::FITKAbaAssembly()
    {
        //创建对象
        const int id = this->getDataObjectID();
        _points = new FITKNodeList;
        _setSurfManager = new FITKComponentManager;
        _setSurfManager->setParentDataIDM(id);
        _refPoints = new FITKAbaRefPointManager;
        _refPoints->setParentDataIDM(id);
        _transformManager = new FITKAbaTransformManager;
        _transformManager->setParentDataIDM(id);
        //线特征
        _wireManager = new FITKAbaWireManager;
        _wireManager->setParentDataIDM(id);
        //添加默认全局坐标系
        FITKAbaTransform* csys = new Interface::FITKAbaTransform(FITKCoordinateSystem::FCSysType::FCSCartesian);
        csys->setDataObjectName(_transformManager->checkName("Datum csys-1"));
        _transformManager->appendDataObj(csys);

        _engineeringFeature = new Interface::FITKAbaAssemblyEngineeringFeature;
        _engineeringFeature->setParentDataID(id);

        _connectorAssignManager = new Interface::FITKAbaConnectorAssignmentManager;
        _connectorAssignManager->setParentDataID(id);

        this->setDataObjectName("Assembly");
    }

    FITKAbaAssembly::~FITKAbaAssembly()
    {
        //释放对象
        if (_setSurfManager != nullptr) delete _setSurfManager;
        if (_points != nullptr) delete _points;
        if (_refPoints != nullptr) delete _refPoints;
        if (_transformManager != nullptr) delete _transformManager;
        if (_wireManager != nullptr) delete _wireManager;
        if (_engineeringFeature != nullptr) delete _engineeringFeature;
        if (_connectorAssignManager != nullptr) delete _connectorAssignManager;
    }

    void FITKAbaAssembly::clear()
    {
        //释放对象
        if (_setSurfManager != nullptr)  _setSurfManager->clear();
        if (_points != nullptr)  _points->removeAllNode();
        if (_refPoints != nullptr)  _refPoints->clear();
        if (_transformManager != nullptr)  _transformManager->clear();
        if (_wireManager != nullptr)  _wireManager->clear();
        if (_engineeringFeature != nullptr)  _engineeringFeature->clear();
        if (_connectorAssignManager != nullptr)  _connectorAssignManager->clear();
        //父类清除instance
        Interface::FITKAssembly::clear();
    }

    Interface::FITKNodeList* FITKAbaAssembly::getPoints()
    {
        return _points;
    }

    Interface::FITKComponentManager* FITKAbaAssembly::getComponentManager()
    {
        return _setSurfManager;
    }

    Interface::FITKAbaRefPointManager* FITKAbaAssembly::getRefPoints()
    {
        //参考点
        return _refPoints;
    }

    Interface::FITKAbaTransformManager* FITKAbaAssembly::getTransformManager()
    {
        return _transformManager;
    }

    FITKAbaWireManager* FITKAbaAssembly::getWireManager()
    {
        return _wireManager;
    }

    QList<Interface::AbaAssComponentInfo> FITKAbaAssembly::getSetInfo(bool recu /*= true*/)
    {
        QList<Interface::AbaAssComponentInfo> setsInfos;
        const int nInstance = this->getDataCount();
        //遍历instance
        for (int i = 0; i < nInstance; ++i)
        {
            FITKAbstractAssInstance* ins = this->getDataByIndex(i);
            if(ins == nullptr) continue;
            const QString insName = ins->getDataObjectName();
            const int insID = ins->getDataObjectID();
            auto insComps = ins->getComponentManager();
            if(insComps == nullptr) continue;
            //ins下的全部集合
            auto setList = insComps->getAllSet(recu);
            for (auto set : setList)
            {
                if(set == nullptr) continue;
                //记录集合信息
                AbaAssComponentInfo info;
                info._nameLabel = QString("%1.%2").arg(insName).arg(set->getDataObjectName());
                info._instanceID = insID;
                info._componentID = set->getDataObjectID();
                info._internal = set->isInternal();
                info._isNodeComp = set->containsType(FITKModelEnum::FITKModelSetType::FMSNode);
                info._component = set;
                info._inheritFromPart = true;
                setsInfos.append(info);
            }
        }

        //ass下的全部集合
        auto setList = _setSurfManager->getAllSet(recu);
        for (auto set : setList)
        {
            if (set == nullptr) continue;
            int insid = -1;
            QString name = set->getDataObjectName();
            //集合上的在instance上
            auto ins = set->getAbstractModelAs<FITKAbstractAssInstance>();
            if (ins)
            {
                insid = ins->getDataObjectID();
            }
            //记录集合信息
            AbaAssComponentInfo info;
            info._nameLabel = name;
            info._instanceID = insid;
            info._componentID = set->getDataObjectID();
            info._internal = set->isInternal();
            info._isNodeComp = set->containsType(FITKModelEnum::FITKModelSetType::FMSNode);
            info._component = set;
            info._inheritFromPart = false;
            setsInfos.append(info);
        }

        return setsInfos;
    }

    QList<Interface::AbaAssComponentInfo> FITKAbaAssembly::getSurfaceInfo()
    {
        QList<Interface::AbaAssComponentInfo> surfsInfos;
        const int nInstance = this->getDataCount();
        //遍历instance
        for (int i = 0; i < nInstance; ++i)
        {
            FITKAbstractAssInstance* ins = this->getDataByIndex(i);
            if (ins == nullptr) continue;
            const QString insName = ins->getDataObjectName();
            const int insID = ins->getDataObjectID();
            auto insComps = ins->getComponentManager();
            if (insComps == nullptr) continue;
            //ins下的全部表面
            auto surfList = insComps->getAllSurface();
            for (auto surf : surfList)
            {
                if (surf == nullptr) continue;
                //记录表面信息
                AbaAssComponentInfo info;
                info._nameLabel = QString("%1.%2").arg(insName).arg(surf->getDataObjectName());
                info._instanceID = insID;
                info._componentID = surf->getDataObjectID();
                info._internal = surf->isInternal(); 
                info._isNodeComp = surf->getMeshSurfaceType() == MeshSurfaceType::SurNode;
                info._component = surf;
                info._inheritFromPart = true;
                surfsInfos.append(info);
            }
        }

        //ass下的全部表面
        auto surfList = _setSurfManager->getAllSurface();
        for (auto surf : surfList)
        {
            if (surf == nullptr) continue;
            int insid = -1;
            QString name = surf->getDataObjectName();
            //表面在instance上
            auto ins = surf->getAbstractModelAs<FITKAbstractAssInstance>();
            if (ins)
            {
                insid = ins->getDataObjectID();
            }
            //记录表面信息
            AbaAssComponentInfo info;
            info._nameLabel = name;
            info._instanceID = insid;
            info._componentID = surf->getDataObjectID(); 
            info._internal = surf->isInternal();
            info._isNodeComp = surf->getMeshSurfaceType() == MeshSurfaceType::SurNode;
            info._component = surf;
            info._inheritFromPart = false;
            surfsInfos.append(info);
        }
        return surfsInfos;
    }

    Interface::FITKAbaRefPoint* FITKAbaAssembly::getRefPointBySet(const int setid, int modelID /*= -1*/)
    {
        Interface::FITKModelSet* set = FITKDATAREPO->getTDataByID<Interface::FITKModelSet>(setid);
        //错误值
        if (set == nullptr || set->getModelSetType() != FITKModelEnum::FITKModelSetType::FMSNode) return nullptr;
        //节点ID
        const int nid = set->getFirstMemberID();
//      const int setModelID = set->getAbsModelID();
         
        //从现有的对象中查找
        const int refCount = _refPoints->getDataCount();
        for (int i =0; i<refCount; ++i)
        {
            auto rfp = _refPoints->getDataByIndex(i);
            if(rfp == nullptr) continue;
            //if (rfp->getAbsModelID() == modelID && rfp->getComponentID() == setid)
            if (rfp->getAbsModelID() == modelID && 
                rfp->getComponentModelID() == modelID && 
                rfp->getNodeID() == nid)
                return rfp;
        }
        //只有一个节点才能创建参考点
        if (set->getMemberCount() != 1) return nullptr;

        //没有找到则创建
        FITKAbaRefPoint* rfPoint = new FITKAbaRefPoint;
        rfPoint->setModel(this->getDataObjectID());
        rfPoint->setComponentModelID(modelID);
        rfPoint->setComponentID(setid);
        //设置名称
        QString name = _refPoints->checkName("_RP-1");
        rfPoint->setDataObjectName(name);
        _refPoints->appendDataObj(rfPoint);
        return rfPoint;
    }

    bool FITKAbaAssembly::getPointCoor(int pointID, double* coor, int modelIndex /*= 0*/)
    {
        Core::FITKNode* node = _points->getNodeByID(pointID);
        if (node == nullptr) return false;
        node->getCoor(coor);
        return true;
    }

    void FITKAbaAssembly::removeDataObj(FITKAbstractDataObject* obj)
    {
        if (obj == nullptr) return;
        const int insID = obj->getDataObjectID();
        //删除相关集合
        QList<Interface::AbaAssComponentInfo> setinfo = this->getSetInfo(true);
        for (Interface::AbaAssComponentInfo set : setinfo)
        {
            if (insID == set._instanceID && set._component)
                delete set._component;
        }
        //移除相关表面
        QList<Interface::AbaAssComponentInfo> surfinfo = this->getSetInfo(true);
        for (Interface::AbaAssComponentInfo surf : surfinfo)
        {
            if (insID == surf._instanceID && surf._component)
                delete surf._component;
        }

        //移除instance
        Interface::FITKAssembly::removeDataObj(obj);
    }

    Interface::FITKAbaAssemblyEngineeringFeature* FITKAbaAssembly::getAssemblyEngineerFeature()
    {
        return _engineeringFeature;
    }

    Interface::FITKAbaConnectorAssignmentManager* FITKAbaAssembly::getConnectorAssignManager()
    {
        return _connectorAssignManager;
    }

    Interface::FITKModelSet* FITKAbaAssembly::getModelSetByMember(Interface::FITKModelEnum::FITKModelSetType t,
        const int modelID, const QList<int> &member)
    {
        if (member.isEmpty()) return nullptr;
        //是否集合
        bool isIns = modelID != this->getDataObjectID();
        //获取全部集合
        QList<AbaAssComponentInfo> setInfos = this->getSetInfo(true);
        for (auto sinfo : setInfos)
        {
            FITKModelSet* set = dynamic_cast<FITKModelSet*>(sinfo._component);
            if(set == nullptr) continue;
            //类型判断
            if(set->getModelSetType() != t) continue;
            //所属对象判断
            if (isIns)  //instance
            {
                if (sinfo._instanceID != modelID) continue;
            }
            else //装配
            {
                if(this->getDataObjectID() != modelID) continue;
            }
            if (set->getAbsoluteMember() == member) return set;
        }
        //没有找到，创建新的集合
        FITKModelSet* set = new FITKModelSet(t);
        set->setInternal(true);
        set->setModel(modelID);
        for (int i : member) set->appendMember(i);
        set->setDataObjectName(_setSurfManager->checkName("Set-1"));
        _setSurfManager->appendDataObj(set);
        return set;
    }

    void FITKAbaAssembly::setAbsDataID(const int id)
    {
        Interface::FITKAssembly::setAbsDataID(id); 
        if (_engineeringFeature) _engineeringFeature->setParentDataID(id);
        if(_setSurfManager) _setSurfManager->setParentDataIDM(id); 
        if(_refPoints) _refPoints->setParentDataIDM(id); 
        if(_transformManager) _transformManager->setParentDataIDM(id);
        if (_wireManager) _wireManager->setParentDataIDM(id);
        if (_engineeringFeature) _engineeringFeature->setParentDataID(id);
        if (_connectorAssignManager) _connectorAssignManager->setParentDataIDM(id);
    }

}

